﻿#include <memory>
#include <functional>
#include "EventBase/EventBase.h"
#include "EventBaseTest.h"

using namespace SystemTool;

enum SUBJECT_EVENT_ENUM
{
	SEND_TEXT = 0
};

struct SubjectArg :public EventArgs
{
	// Text
	std::string strText;

	SubjectArg()
	{
		strText = "";
	}
};

class ISubject:public IEventBase
{
public:
	// Say something
	virtual void Say(std::string strText) = 0;
};

class Subject:public EventBase<ISubject>
{
public:
	virtual ~Subject()
	{

	}

	// Say something
	virtual void Say(std::string strText)
	{
		SubjectArg Args;

		Args.strText = strText;

		Notify(this, SEND_TEXT, &Args);
	}
};

class Observer
{
public:
	Observer(ISubject* pSubject)
	{
		m_pSubject = pSubject;

		ListenToSubject();
	}

	~Observer()
	{
		UnlistenToSubject();
	}

	// Listen to the subject
	void ListenToSubject()
	{
		if (m_pSubject == NULL)
		{
			return;
		}

		m_fFunc = std::bind(&Observer::HandleEvents, this, std::placeholders::_1);

		m_pSubject->Listen(this, m_fFunc, SEND_TEXT);
	}

	// UnListen to the subject
	void UnlistenToSubject()
	{
		if (m_pSubject == NULL)
		{
			return;
		}

		m_pSubject->UnListen(this, m_fFunc, SEND_TEXT);
	}

	// Handle the subject events
	void HandleEvents(EventPara& para)
	{
		if (para.iEventID == SEND_TEXT)
		{
			SubjectArg* pArgs = static_cast<SubjectArg*>(para.pArgs);

			std::cout << pArgs->strText << std::endl;
		}
	}

private:
	// Subject 
	ISubject* m_pSubject;

	// Listen function
	IEventHandler::HandlerFunc m_fFunc;
};

int TestEventBase()
{
	// Create a subject
	ISubject* pSubject = new Subject();

	// Create an observer and listen to the subject
	Observer* pObserver = new Observer(pSubject);

	// Do something by subject and observer can sense of it
	pSubject->Say("very good everyone!");

	if (pObserver)
	{
		delete pObserver;

		pObserver = NULL;
	}

	if (pSubject)
	{
		delete pSubject;

		pSubject = NULL;
	}
	
	return 0;
}
